/*******************************************************************************
 * This source file contains builtin-functions implements.
 *
 * @author LoveLonelyTime
 * @version 1.1
 * @date 2021-2021
 * @copyright GNU Public License.
 ******************************************************************************/

#include <string>
#include <algorithm>
#include <cmath>

#include "builtin.h"
#include "language.h"
#include "exception.h"

SBASIC::sbasic_decimal_type builtin_min(const std::vector<SBASIC::sbasic_decimal_type> &args)
{
    if (args.size() != 2)
    {
        throw SBASIC::Exception("Runtime", "MIN must have 2 paramters,but get " + std::to_string(args.size()) + " paramters", 0);
    }

    return std::min(args[0], args[1]);
}

SBASIC::sbasic_decimal_type builtin_max(const std::vector<SBASIC::sbasic_decimal_type> &args)
{
    if (args.size() != 2)
    {
        throw SBASIC::Exception("Runtime", "MAX must have 2 paramters,but get " + std::to_string(args.size()) + " paramters", 0);
    }

    return std::max(args[0], args[1]);
}

SBASIC::sbasic_decimal_type builtin_sin(const std::vector<SBASIC::sbasic_decimal_type> &args)
{
    if (args.size() != 1)
    {
        throw SBASIC::Exception("Runtime", "SIN must have 1 paramters,but get " + std::to_string(args.size()) + " paramters", 0);
    }

    return std::sin(args[0]);
}

SBASIC::sbasic_decimal_type builtin_cos(const std::vector<SBASIC::sbasic_decimal_type> &args)
{
    if (args.size() != 1)
    {
        throw SBASIC::Exception("Runtime", "COS must have 1 paramters,but get " + std::to_string(args.size()) + " paramters", 0);
    }

    return std::cos(args[0]);
}

SBASIC::sbasic_decimal_type builtin_log(const std::vector<SBASIC::sbasic_decimal_type> &args)
{
    if (args.size() != 1)
    {
        throw SBASIC::Exception("Runtime", "LOG must have 1 paramters,but get " + std::to_string(args.size()) + " paramters", 0);
    }

    return std::log(args[0]);
}

SBASIC::sbasic_decimal_type builtin_abs(const std::vector<SBASIC::sbasic_decimal_type> &args)
{
    if (args.size() != 1)
    {
        throw SBASIC::Exception("Runtime", "ABS must have 1 paramters,but get " + std::to_string(args.size()) + " paramters", 0);
    }

    return std::abs(args[0]);
}

SBASIC::sbasic_decimal_type builtin_ver(const std::vector<SBASIC::sbasic_decimal_type> &args)
{
    return VERSION;
}

void injection_builtin(SBASIC::FunctionTable *ftp)
{
    ftp->put_function("MIN", builtin_min);
    ftp->put_function("MAX", builtin_max);
    ftp->put_function("SIN", builtin_sin);
    ftp->put_function("COS", builtin_cos);
    ftp->put_function("LOG", builtin_log);
    ftp->put_function("ABS", builtin_abs);
    ftp->put_function("VER", builtin_ver);
}